/***************************************************************
*  Name:  hmac
*	   
*  Synopsis:  hmac implementation
*    	    
*  Description:
*     	    
*  History:
*      	         pascal - Feb 5, 2012:  Created.
*
***************************************************************/

/* $Id$ */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "digest.h"


  
int hmac(unsigned char * key, int keylen, unsigned char *text, int text_len, digest_ctx * digest)
{

        unsigned char * ipad;
        int k;
        unsigned char *hash;
        
        ipad = (unsigned char *)malloc(DIGEST_BLOCK_SIZE);

        memset(ipad, 0x36, DIGEST_BLOCK_SIZE);
        
        // if key > than 64 bytes needs to be hashed

        for(k=0; k<keylen; k++)
                ipad[k]^=key[k];

        update_digest(digest, ipad, DIGEST_BLOCK_SIZE);
        update_digest(digest, text, text_len);
        finalize_digest(digest);

        unsigned int hashlen = digest->hash_len*sizeof(int);
        hash = (unsigned char*)malloc(hashlen);
        memcpy(hash, digest->hash, hashlen);

        // need to reinitialise the digest
        new_digest(digest);
        
        memset(ipad, 0x5C, DIGEST_BLOCK_SIZE);
        for(k=0; k<keylen; k++)
                ipad[k]^=key[k];

        update_digest(digest, ipad, DIGEST_BLOCK_SIZE);
        update_digest(digest, hash, hashlen);
        finalize_digest(digest);                    

        return 0;
}




#ifdef TEST

main1(int argc, char *argv[])
{
        unsigned char *key;
        int key_len;
        unsigned char *text;
        int text_len;
        digest_ctx digest;

        key = "Jefe";
        key_len = strlen(key);
        text = "what do ya want for nothing?";
        text_len = strlen(text);
        
        new_md5_digest(&digest);
        printf("key:[%s]\n",key);
        printf("text:[%s]\n",text);
        hmac(key, key_len, text, text_len, &digest);

        print_digest("hmac", &digest);
        exit(0);
}

usage()
{
        fprintf(stderr,"usage: %s -sha1|md5 [0x]key [0x]text\n","hmac");
        exit(1);
}


/* hex parser */
int hexdecode(char* input, unsigned char **decoded)
{
        int i;
        int len;
        
        if ( strncmp( "0x", input, 2 ) )
        {
                len = strlen( input ) + 1;
                *decoded = malloc( len );
                strcpy( *decoded, input );
                len--;
        }
        else
        {
                len = ( strlen( input ) >> 1 ) - 1;
                *decoded = malloc( len );
                for ( i = 2; i < strlen( input ); i += 2 )
                {
                        (*decoded)[ ( ( i / 2 ) - 1 ) ] =
                                ( ( ( input[ i ] <= '9' ) ? input[ i ] - '0' : 
                                    ( ( tolower( input[ i ] ) ) - 'a' + 10 ) ) << 4 ) |
                                ( ( input[ i + 1 ] <= '9' ) ? input[ i + 1 ] - '0' : 
                                  ( ( tolower( input[ i + 1 ] ) ) - 'a' + 10 ) );
                }
        } 
 
  return len;
        
}



main(int argc, char *argv[])
{
        digest_ctx ctx;
        unsigned char * key, *text;
        int keylen, textlen;
        
        if(argc<4)
                main1(0,0); //usage();

        if (!strcmp(argv[1], "-sha1")) {
                new_sha1_digest(&ctx);
        } else if (!strcmp(argv[1], "-md5")) {
                new_md5_digest(&ctx);
        } else 
                usage();

        keylen = hexdecode(argv[2],&key);
        textlen = hexdecode(argv[3], &text);

        hmac(key, keylen, text, textlen, &ctx);

        print_digest("hmac:", &ctx);

        exit(0);
}
#endif
